Bindable richTextBox still hanging in memory {WPF, Caliburn.Micro}

Posted by Paul on Stack Overflow See other posts from Stack Overflow or by Paul
Published on 2011-01-08T10:10:28Z Indexed on 2011/01/08 18:53 UTC
Read the original article Hit count: 750

Hi, I use in WFP Caliburn.Micro Framework. I need bindable richTextbox for Document property. I found many ways how do it bindable richTextBox.

But I have one problem. From parent window I open child window. Child window consist bindable richTextBox user control.

After I close child window and use memory profiler view class with bindabelrichTextBox control and view model class is still hanging in memory. -> this cause memory leaks.

If I use richTextBox from .NET Framework or richTextBox from Extended WPF Toolkit it doesn’t cause this memory leak problem.

I can’t identified problem in bindable richTextBox class.

Here is ist class for bindable richTextBox:

Base class can be from .NET or Extended toolkit.

  /// <summary>
    /// Represents a bindable rich editing control which operates on System.Windows.Documents.FlowDocument
    /// objects.    
    /// </summary>
    public class BindableRichTextBox : RichTextBox
    {

        /// <summary>
        /// Identifies the <see cref="Document"/> dependency property.
        /// </summary>
        public static readonly DependencyProperty DocumentProperty = DependencyProperty.Register("Document",
            typeof(FlowDocument), typeof(BindableRichTextBox));

        /// <summary>
        /// Initializes a new instance of the <see cref="BindableRichTextBox"/> class.
        /// </summary>
        public BindableRichTextBox()
            : base()
        {
        }


        /// <summary>
        /// Initializes a new instance of the <see cref="BindableRichTextBox"/> class.
        /// </summary>
        /// <param title="document">A <see cref="T:System.Windows.Documents.FlowDocument"></see> to be added as the initial contents of the new <see cref="T:System.Windows.Controls.BindableRichTextBox"></see>.</param>
        public BindableRichTextBox(FlowDocument document)
            : base(document)
        {
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.FrameworkElement.Initialized"></see> event. This method is invoked whenever <see cref="P:System.Windows.FrameworkElement.IsInitialized"></see> is set to true internally.
        /// </summary>
        /// <param title="e">The <see cref="T:System.Windows.RoutedEventArgs"></see> that contains the event data.</param>
        protected override void OnInitialized(EventArgs e)
        {
            // Hook up to get notified when DocumentProperty changes.
            DependencyPropertyDescriptor descriptor = DependencyPropertyDescriptor.FromProperty(DocumentProperty, typeof(BindableRichTextBox));
            descriptor.AddValueChanged(this, delegate
            {
                // If the underlying value of the dependency property changes,
                // update the underlying document, also.
                base.Document = (FlowDocument)GetValue(DocumentProperty);

            });

            // By default, we support updates to the source when focus is lost (or, if the LostFocus
            // trigger is specified explicity.  We don't support the PropertyChanged trigger right now.
            this.LostFocus += new RoutedEventHandler(BindableRichTextBox_LostFocus);

            base.OnInitialized(e);

        }

        /// <summary>
        /// Handles the LostFocus event of the BindableRichTextBox control.
        /// </summary>
        /// <param title="sender">The source of the event.</param>
        /// <param title="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        void BindableRichTextBox_LostFocus(object sender, RoutedEventArgs e)
        {

            // If we have a binding that is set for LostFocus or Default (which we are specifying as default)
            // then update the source.
            Binding binding = BindingOperations.GetBinding(this, DocumentProperty);
            if (binding.UpdateSourceTrigger == UpdateSourceTrigger.Default ||
                binding.UpdateSourceTrigger == UpdateSourceTrigger.LostFocus)
            {
                BindingOperations.GetBindingExpression(this, DocumentProperty).UpdateSource();
            }

        }

        /// <summary>
        /// Gets or sets the <see cref="T:System.Windows.Documents.FlowDocument"></see> that represents the contents of the <see cref="T:System.Windows.Controls.BindableRichTextBox"></see>.
        /// </summary>
        /// <value></value>
        /// <returns>A <see cref="T:System.Windows.Documents.FlowDocument"></see> object that represents the contents of the <see cref="T:System.Windows.Controls.BindableRichTextBox"></see>.By default, this property is set to an empty <see cref="T:System.Windows.Documents.FlowDocument"></see>.  Specifically, the empty <see cref="T:System.Windows.Documents.FlowDocument"></see> contains a single <see cref="T:System.Windows.Documents.Paragraph"></see>, which contains a single <see cref="T:System.Windows.Documents.Run"></see> which contains no text.</returns>
        /// <exception cref="T:System.ArgumentException">Raised if an attempt is made to set this property to a <see cref="T:System.Windows.Documents.FlowDocument"></see> that represents the contents of another <see cref="T:System.Windows.Controls.RichTextBox"></see>.</exception>
        /// <exception cref="T:System.ArgumentNullException">Raised if an attempt is made to set this property to null.</exception>
        /// <exception cref="T:System.InvalidOperationException">Raised if this property is set while a change block has been activated.</exception>
        public new FlowDocument Document
        {
            get { return (FlowDocument)GetValue(DocumentProperty); }
            set { SetValue(DocumentProperty, value); }
        }

    }

Thank fro help and advice.

Qucik example:

Child window with .NET richTextBox

<Window x:Class="WpfApplication2.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
    <Grid>
        <RichTextBox                        Background="Green"
                                            VerticalScrollBarVisibility="Auto" 
                                            HorizontalScrollBarVisibility="Auto"
                                            FontSize="13"
                                            Margin="4,4,4,4" 
                                            Grid.Row="0"/>
    </Grid>
</Window>

This window I open from parent window:

        var w = new Window1();
        w.Show();

Then close this window, check with memory profiler and it memory doesn’t exist any object of window1 - richTextBox. It’s Ok.

But then I try bindable richTextBox:

Child window 2:

<Window x:Class="WpfApplication2.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:Controls="clr-namespace:WpfApplication2.Controls" 
        Title="Window2" Height="300" Width="300">
    <Grid>
        <Controls:BindableRichTextBox       Background="Red"
                                            VerticalScrollBarVisibility="Auto" 
                                            HorizontalScrollBarVisibility="Auto"
                                            FontSize="13"
                                            Margin="4,4,4,4" 
                                            Grid.Row="0" />
    </Grid>
</Window>

Open child window 2, close this child window and in memory are still alive object of this child window also bindable richTextBox object.

© Stack Overflow or respective owner

Related posts about wpf

Related posts about binding